"""
This interface is for Windows only, otherwise use SocketCAN.
"""
import ctypes
import logging
import os
import time
import logging
from typing import Optional
from can import BusABC, Message
from ctypes import *
import platform
from time import sleep
from sdk.usb_device import *
from sdk.usb2can import *
from sdk.can_uds import *
from types import ModuleType
from typing import (
    Any,
    Callable,
    Dict,
    List,
    NamedTuple,
    Optional,
    Sequence,
    Tuple,
    Union,
    cast,
)

# Set up logging
log = logging.getLogger("can.toomoss")


class ToomossBus(BusABC):

    def __init__(
            self,
            channel: Optional[int] = None,
            bitrate: int = 500000,
            serial: Optional[str] = None,
            **kwargs,
    ):
        self.CAN = channel
        self.DevHandles = (c_uint * 20)()
        # Scan device
        ret = USB_ScanDevice(byref(self.DevHandles))
        if ret == 0:
            print("No device connected!")
            exit()
        else:
            print("Have %d device connected!" % ret)
        # Open device
        ret = USB_OpenDevice(self.DevHandles[0])
        if bool(ret):
            print("Open device success!")
        else:
            print("Open device faild!")
            exit()
        # 初始化CAN
        CANConfig = CAN_INIT_CONFIG()
        CANConfig.CAN_Mode = 0x80  # 1-自发自收模式，0-正常模式
        CANConfig.CAN_ABOM = 0
        CANConfig.CAN_NART = 1
        CANConfig.CAN_RFLM = 0
        CANConfig.CAN_TXFP = 1
        # 配置波特率,波特率 = 100M/(BRP*(SJW+BS1+BS2))
        # CANConfig.CAN_BRP_CFG3 = 25;
        # CANConfig.CAN_BS1_CFG1 = 2;
        # CANConfig.CAN_BS2_CFG2 = 1;
        # CANConfig.CAN_SJW = 1;
        # 配置波特率,波特率 = 42M/(BRP*(SJW+BS1+BS2))
        CANConfig.CAN_BRP_CFG3 = 4;
        CANConfig.CAN_BS1_CFG1 = 16;
        CANConfig.CAN_BS2_CFG2 = 4;
        CANConfig.CAN_SJW = 1;
        ret = CAN_Init(self.DevHandles[0], self.CAN, byref(CANConfig))
        if (ret != CAN_SUCCESS):
            print("Config CAN2 failed!")
            exit()
        else:
            print("Config CAN2 Success!")
        # 配置过滤器，必须配置，否则可能无法收到数据
        CANFilter = CAN_FILTER_CONFIG()
        CANFilter.Enable = 1
        CANFilter.ExtFrame = 0
        CANFilter.FilterIndex = 0
        CANFilter.FilterMode = 0
        CANFilter.MASK_IDE = 0
        CANFilter.MASK_RTR = 0
        CANFilter.MASK_Std_Ext = 0
        ret = CAN_Filter_Init(self.DevHandles[0], self.CAN, byref(CANFilter))
        if ret != CAN_SUCCESS:
            exit()
        BusABC.__init__(self, channel=channel, **kwargs)

    def send(self, msg: Message, timeout: Optional[float] = None) -> None:
        self._send_sequence(msg)

    def _send_sequence(self, msgs: Message) -> int:
        """Send messages and return number of successful transmissions."""
        # if self.fd:
        #     return self._send_can_fd_msg_sequence(msgs)
        # else:
        return self._send_can_msg_sequence(msgs)

    def _send_can_msg_sequence(self, msgs: Message) -> int:
        """Send CAN messages and return number of successful transmissions."""
        xl_event_array = self._build_xl_event(msgs)
        SendedNum = CAN_SendMsg(self.DevHandles[0], self.CAN, byref(xl_event_array), 1)
        return SendedNum

    @staticmethod
    def _build_xl_event(msg: Message) -> CAN_MSG:
        msg_id = msg.arbitration_id
        CanMsg = CAN_MSG()
        if msg.is_extended_id:
            CanMsg.ExternFlag = 1
        if msg.is_remote_frame:
            CanMsg.RemoteFlag = 1
        CanMsg.ID = msg_id
        CanMsg.DataLen = msg.dlc
        for j in range(0, CanMsg.DataLen):
            CanMsg.Data[j] = msg.data[j]
        return CanMsg

    def _recv_internal(
            self, timeout: Optional[float]
    ) -> Tuple[Optional[Message], bool]:
        end_time = time.time() + timeout if timeout is not None else None
        while True:
            msg, res = self._recv_can()
            if res > 0:
                if msg:
                    return msg, False
            else:
                return None,False

    def _recv_can(self):
        CanMsgBuffer = (CAN_MSG*10240)()
        CanNum = CAN_GetMsg(self.DevHandles[0], self.CAN, byref(CanMsgBuffer))
        if CanNum > 0:
            for i in range(0, CanNum):
                return Message(
                    timestamp=CanMsgBuffer[i].TimeStamp,
                    arbitration_id=CanMsgBuffer[i].ID,
                    is_extended_id=False,
                    is_remote_frame=False,
                    is_rx=True,
                    is_fd=False,
                    dlc=CanMsgBuffer[i].DataLen,
                    data=CanMsgBuffer[i].Data,
                ), CanNum
        else:
            return None, CanNum

    def shutdown(self):
        """
        Shuts down connection to the device safely.

        :raise cam.CanOperationError: is closing the connection did not work
        """
        super().shutdown()

    def _detect_available_configs(self):
        pass

    def detect_available_configs(self, serial_matcher: Optional[str] = None):
        pass
